package pl.enigmatic.parser.xml;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import pl.enigmatic.util.Enums;
import pl.enigmatic.parser.string.Converter;


/**
 * This enumeration holds information description to be put in the root of the xml document. It tells the parser how to treat some values during
 * parsing process.
 * @author reggie_7
 */
public enum ParsingMetadata {
	/** Tells whether to treat the metadata String name attribute as the property name if the parsed class has a name property */
	META_NAME_IS_NAME_PROPERTY(Boolean.class, true);

	public final static String XMLNS = Parser.XMLNS("parsing");

	private final Converter<?> converter;
	private final Object defaultValue;

	private ParsingMetadata(final Class<?> clazz, final Object defaultValue) {
		this.defaultValue = defaultValue;
		converter = Converter.createDefaultConverter(clazz);
	}

	public Object getDefaultValue() {
		return defaultValue;
	}

	@Override
	public String toString() {
		return Enums.convertNameToJavaStyle(this);
	}

	public static ParsingMetadata from(final Node node) {
		return Enum.valueOf(ParsingMetadata.class, Enums.convertNameFromJavaStyle(node.getLocalName()));
	}

	public static Map<ParsingMetadata, Object> clean(final Document doc) {
		final Map<ParsingMetadata, Object> res = new HashMap<ParsingMetadata, Object>();
		final Element xml = doc.getDocumentElement();
		final NamedNodeMap attr = xml.getAttributes();
		final HashSet<String> remove = new HashSet<String>();
		for (int i = 0; i < attr.getLength(); i++) {
			final Node item = attr.item(i);
			if (XMLNS.equals(item.getNamespaceURI())) {
				remove.add(item.getNodeName());
				final ParsingMetadata key = from(item);
				res.put(key, key.converter.convert(item.getNodeValue()));
			}
		}
		for (final String item : remove) {
			attr.removeNamedItem(item);
		}
		return res;
	}
}
